package com.socket.client.manager;

import cn.hutool.core.util.StrUtil;
import com.socket.client.custom.KeywordSupport;
import com.socket.client.feign.ShieldUserApi;
import com.socket.client.feign.param.ShieldParam;
import com.socket.client.model.base.BaseUser;
import com.socket.client.model.chat.ChatMessage;
import com.socket.client.model.chat.ChatUser;
import com.socket.core.constant.ChatProperties;
import com.socket.core.enums.Setting;
import com.socket.core.manage.SocketRedisManager;
import com.socket.core.model.command.enmus.Authn;
import com.socket.core.util.Wss;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Socket权限管理器
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AuthnManager {
    private final SocketRedisManager redisManager;
    private final KeywordSupport keywordSupport;
    private final ChatProperties properties;
    private final GroupManager groupManager;
    private final UserManager userManager;
    private final ShieldUserApi shieldUserApi;

    /**
     * 获取指定用户屏蔽列表
     *
     * @param user 用户
     * @return 屏蔽列表
     */
    public List<String> getShield(ChatUser user) {
        ShieldParam param = new ShieldParam();
        param.setGuid(user.getGuid());
        return shieldUserApi.getShieldList(param).getData();
    }

    /**
     * 检查指定用户禁言情况，若用户被禁言将发送一条系统通知
     */
    public void checkMute(ChatUser user) {
        long time = redisManager.getMuteTime(user.getGuid());
        if (time > 0) {
            user.send(String.valueOf(time), Authn.MUTE, user);
        }
    }

    /**
     * 检查消息合法性
     *
     * @param user      发起者
     * @param message   消息
     * @param sensitive 敏感关键词检查
     * @return 是否通过
     */
    public boolean verifyMessage(ChatUser user, ChatMessage message, boolean sensitive) {
        String content = message.getContent();
        if (content == null) {
            return true;
        }
        content = StrUtil.sub(content, 0, properties.getMaxMessageLength());
        // 违规字符检查的代替方案
        content = content.replace("<", "&lt;");
        content = content.replace(">", "&gt;");
        if (sensitive && keywordSupport.containsSensitive(content)) {
            user.reject("消息包含敏感关键词，请检查后重新发送", message);
            return false;
        }
        message.setContent(content);
        return true;
    }

    /**
     * 检查指定用户是否被目标屏蔽（优先通过缓存加载）
     */
    public boolean shield(ChatUser source, ChatUser target) {
        return getShield(source).contains(target.getGuid());
    }

    /**
     * 连续发言标记（排除所有者） <br>
     * 10秒内超过一定次数会被禁止一段时间发言
     */
    public void operateMark(ChatUser user) {
        long time = TimeUnit.HOURS.toSeconds(properties.getFrequentSpeechMuteTime());
        if (redisManager.incrSpeak(user.getGuid()) > properties.getFrequentSpeechThreshold()) {
            redisManager.setMute(user.getGuid(), time);
            // b结尾 特殊的刷屏标记
            user.send(time + "b", Authn.MUTE, user);
        }
    }

    /**
     * 检查指定用户是否被禁言
     *
     * @param user 用户
     * @return true被禁言
     */
    public boolean isMute(ChatUser user) {
        return redisManager.getMuteTime(user.getGuid()) > 0;
    }

    /**
     * 检查用户/群组是否存在
     *
     * @param target 目标uid
     * @return 是否存在
     */
    public boolean notHas(String target) {
        return getBaseUser(target) == null;
    }

    /**
     * 获取基础用户/群组信息
     */
    public BaseUser getBaseUser(String guid) {
        return Wss.isGroup(guid) ? groupManager.getGroup(guid) : userManager.getUser(guid);
    }

    /**
     * 获取系统管理员设置
     */
    public boolean getSetting(Setting setting) {
        return redisManager.getSetting(setting.getKey());
    }
}
